飞桨框架v2.3 API最新升级!对科学计算、概率分布和稀疏Tensor等提供更全面支持!
2022年5月飞桨框架2.3版本正式发布,相比飞桨框架2.2版本,API 体系更加丰富,新增了100多个 API,覆盖自动微分、概率分布、稀疏Tensor、拟牛顿优化器、线性代数、框架性能分析、硬件设备管理、视觉和语音领域等方面。整体上进一步丰富了飞桨框架动静统一、高低融合的 API 体系。
下面对每一类新增的 API 及其应用场景进行详细介绍,方便快速理解和上手。
1
新增自动微分 API
以更好支持科学计算
基于延迟计算求解雅可比矩阵与海森矩阵
import paddle
def func(x, y):
return paddle.matmul(x, y)
x = paddle.to_tensor([[1., 2.], [3., 4.]])
J = paddle.incubate.autograd.Jacobian(func, [x, x])
print(J[:, :])
# Tensor(shape=[4, 8], dtype=float32, place=Place(gpu:0), stop_gradient=False,
# [[1., 3., 0., 0., 1., 0., 2., 0.],
# [2., 4., 0., 0., 0., 1., 0., 2.],
# [0., 0., 1., 3., 3., 0., 4., 0.],
# [0., 0., 2., 4., 0., 3., 0., 4.]])
print(J[0, :])
# Tensor(shape=[8], dtype=float32, place=Place(gpu:0), stop_gradient=False,
# [1., 3., 0., 0., 1., 0., 2., 0.])
print(J[:, 0])
# Tensor(shape=[4], dtype=float32, place=Place(gpu:0), stop_gradient=False,
# [1., 2., 0., 0.])
def _jac_func(*xs):
jac = Jacobian(func, xs, is_batched=is_batched)
if (is_batched and jac.shape[1] != 1) or (not is_batched and
jac.shape[0] != 1):
raise RuntimeError(
"The function given to Hessian shoud return as single element Tensor or batched single element Tensor."
)
return jac[:, 0, :] if is_batched else jac[0, :]
self.symbolic = Jacobian(_jac_func, xs, is_batched=is_batched)
使用 jvp 和 vjp 计算前向微分与反向微分
2
体系化完善概率分布类 API
以支持更多应用场景
更为灵活完备的 API 体系
import paddle
beta = paddle.distribution.Beta(0.5, 0.5)
samples = beta.sample((10000,))
import paddle
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
normal = paddle.distribution.Normal(0., 1.)
samples = normal.sample([10000])
sns.distplot(samples)
plt.title('samples from a Norma(0., 1.)')
plt.show()
affine = paddle.distribution.AffineTransform(paddle.to_tensor(2.), paddle.to_tensor(2.))
transformed_samples = affine.forward(samples)
sns.distplot(transformed_samples)
plt.title('samples from a AffineTransform(2., 2.) Normal(0., 1.)')
plt.show()
import paddle
p = paddle.distribution.Beta(alpha=0.5, beta=0.5)
q = paddle.distribution.Beta(alpha=0.3, beta=0.7)
print(paddle.distribution.kl_divergence(p, q))
# Tensor(shape=[1], dtype=float32, place=CUDAPlace(0), stop_gradient=True,
# [0.21193528]
import paddle
# 基于标准正态分布和仿射变换,构建新的高阶分布
d = paddle.distribution.TransformedDistribution(
paddle.distribution.Normal(0., 1.),
[paddle.distribution.AffineTransform(paddle.to_tensor(1.), paddle.to_tensor(2.))]
)
print(d.sample([10]))
# Tensor(shape=[10], dtype=float32, place=Place(gpu:0), stop_gradient=True,
# [-0.10697651, 3.33609009, -0.86234951, 5.07457638, 0.75925219,
# -4.17087793, 2.22579336, -0.93845034, 0.66054249, 1.50957513])
print(d.log_prob(paddle.to_tensor(0.5)))
# Tensor(shape=[1], dtype=float32, place=Place(gpu:0), stop_gradient=True,
# [-1.64333570])
更为完善的向量化语义
采样形状(sample_shape):向量化批量采样过程; 批形状(batch_shape):向量化不同参数的分布; 事件形状(event_shape):向量化多元分布;
import paddle
# 创建两个3元多项分布,分布1概率为[0.2, 0.3, 0.5],分布2概率为[0.1, 0.9, 0.8],因此事件形状为3,批形状为2
multinomial = paddle.distribution.Multinomial(total_count=10, probs=paddle.to_tensor([[0.2, 0.3, 0.5], [0.1, 0.9, 0.8]]))
print('event_shape: ', multinomial.event_shape)
print('batch_shape: ', multinomial.batch_shape)
# 采样形状为4,因此最终样本形状为[4, 2, 3]
samples = multinomial.sample((4,))
print('sample_shape: ', samples.shape)
# event_shape: (3,)
# batch_shape: (2,)
# sample_shape: [4, 2, 3]
更为丰富的采样算法
支持反向传播
def rsample(self, sample_shape):
shape = self._extended_shape(sample_shape)
eps = _standard_normal(shape, dtype=self.loc.dtype, device=self.loc.device)
return self.loc + eps * self.scale
3
新增创建2种稀疏 Tensor 的 API
支持和常规 Tensor 进行转换
COO 稀疏格式
indices = [[0, 1, 1, 2, 3, 3],
[1, 0, 3, 2, 1, 3]]
values = [1, 2, 3, 4, 5, 6]
dense_shape = [4, 4]
coo = paddle.sparse.sparse_coo_tensor(indices, values, dense_shape)
print(coo)
# Tensor(shape=[4, 4], dtype=paddle.int64, place=Place(gpu:0), stop_gradient=True,
# indices=[[0, 1, 1, 2, 3, 3],
# [1, 0, 3, 2, 1, 3]],
# values=[1, 2, 3, 4, 5, 6])
CSR 稀疏格式
crows = [0, 1, 3, 4, 6]
cols = [1, 0, 3, 2, 1, 3]
values = [1, 2, 3, 4, 5, 6]
dense_shape = [4, 4]
csr = paddle.sparse.sparse_csr_tensor(crows, cols, values, dense_shape)
print(csr)
# Tensor(shape=[4, 4], dtype=paddle.int64, place=Place(gpu:0), stop_gradient=True,
# crows=[0, 1, 3, 4, 6],
# cols=[1, 0, 3, 2, 1, 3],
# values=[1, 2, 3, 4, 5, 6])
稀疏与稠密 Tensor 互转
dense = paddle.to_tensor([[0, 1, 0, 2],
[0, 0, 3, 4]], dtype='float32')
coo = dense.to_sparse_coo(sparse_dim=2)
# Tensor(shape=[2, 4], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True,
# indices=[[0, 0, 1, 1],
# [1, 3, 2, 3]],
# values=[1., 2., 3., 4.])
csr = dense.to_sparse_csr()
# Tensor(shape=[2, 4], dtype=paddle.float32, place=Place(gpu:0), stop_gradient=True,
# crows=[0, 2, 4],
# cols=[1, 3, 2, 3],
# values=[1., 2., 3., 4.])
4
新增拟牛顿法二阶优化 API
import paddle
def func(x):
return paddle.dot(x, x)
x0 = paddle.to_tensor([1.3, 2.7])
results = paddle.incubate.optimizer.functional.minimize_bfgs(func, x0)
print("is_converge: ", results[0])
print("the minimum of func is: ", results[2])
# is_converge: is_converge: Tensor(shape=[1], dtype=bool, place=Place(gpu:0), stop_gradient=True,
# [True])
# the minimum of func is: Tensor(shape=[2], dtype=float32, place=Place(gpu:0), stop_gradient=True,
# [0., 0.])
5
其他新增 API
扩展线性代数 API
max_memory_allocated max_memory_reserved memory_allocated 和 memory_reserved
新增 Viterbi 解码 API:
paddle.text.ViterbiDecoder 和 paddle.text.viterbi_decode
已用于序列标注模型的预测。
6
结语